﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Business.Compta;
using DevExpress.Wpf.Editors.Settings;
using Manageo;

namespace Compta
{
    /// <summary>
    /// Interaction logic for SyntheseUser.xaml
    /// </summary>
    public partial class SyntheseUser : UserControl
    {
        private ObservableRangeCollection<Account> accounts = new ObservableRangeCollection<Account>();
        public ObservableRangeCollection<Account> Accounts
        {
            get
            {
                return accounts;
            }
        }

        private ObservableRangeCollection<User> users = new ObservableRangeCollection<User>();        
        public ObservableRangeCollection<User> Users
        {
            get
            {
                if (users == null)
                {
                    this.users = new ObservableRangeCollection<User>();
                }
                return users;
            }
        }

        private ObservableRangeCollection<SynthesePerUser> syntheses = new ObservableRangeCollection<SynthesePerUser>();

        public ObservableRangeCollection<SynthesePerUser> Syntheses
        {
            get
            {
                if (syntheses == null)
                {
                    this.syntheses = new ObservableRangeCollection<SynthesePerUser>();
                }
                return syntheses;
            }
        }

        public SyntheseUser(int idUser)
        {
            InitializeComponent();
            accounts.ReplaceRange(DAO.Compta.ComptaAccountsDAO.getAllAccounts(idUser));
        }

        private void getSyntheseForAccount(int idAccount, double solde) 
        {
            Dictionary<int, double> result = new Dictionary<int, double>();
            Dictionary<int, double> categories = new Dictionary<int, double>();

            // 1 - AllLines, ComptaLine, IdUser!=-1
            List<ComptaLine> allLines = getAllLinesForAccount(idAccount);
            var perUser = from a in allLines
                          where a.IsComptaLineSup == false && a.IdUser != -1
                          group a by a.IdUser into g
                          select new
                          {
                              IdUser = g.Key,
                              Total = g.Sum(x => x.Amount)
                          };
            foreach (var item in perUser)
            {
                if (!result.ContainsKey(item.IdUser))
                    result.Add(item.IdUser, 0);
                result[item.IdUser] = result[item.IdUser] + item.Total;
            }
            var _persoUser = from a in allLines
                            where a.IsComptaLineSup == true
                            select a;

            // 2 - AllLines, ComptaLineSup
            // attention, on inverse les signes pour les LinesSup :
            // ex : si Sandra a payé la mutuelle 60 euros, sur le compte commun on a -60 euros de dépensé
            // par contre, pour la synthèse, c'est Sandra qui a payé donc +60
            // et inversement pour les crédit
            var persoUser = from al in allLines
                          where al.IsComptaLineSup == true
                          group al by al.IdUser into gl
                          select new
                          {
                              IdUser = gl.Key,
                              Total = +gl.Sum(xl => xl.Debit) - gl.Sum(xl => xl.Credit)
                          }
                          ;

            foreach (var item in persoUser)
            {
                if (!result.ContainsKey(item.IdUser))
                    result.Add(item.IdUser, 0);
                result[item.IdUser] = result[item.IdUser] + item.Total;
            }

            // 3 - AllLines, ComptaLine, IdUser == -1
            List<CategoriesPerUser> categPerUser = getAllCategoriesPerUser(idAccount);

            // on enlève l'Id = -1
            double proportion = 1.00 / (this.users.Count - 1);

            var perCategories = from a in allLines
                          where ((!a.IsComptaLineSup && a.IdUser == -1) || a.IsComptaLineSup)
                          group a by (a.Category==null?-1:a.Category.IdCategory) into g
                          select new
                          {
                              IdCateg = (g.Key==null)?-1:g.Key,
                              Total = g.Sum(xl => xl.Credit) - g.Sum(xl => xl.Debit) 
                          };
            bool alreadyDone = false;

            foreach (var item in perCategories)
            {
                alreadyDone = false;
                foreach (User usr in users)
                {
                    var perCategories2 = from a in categPerUser
                                         where a.IdCategory == item.IdCateg && a.IdUser == usr.Id
                                         select new {Percent = a.Percent};

                    foreach (var item2 in perCategories2)
                    {
                        if (!result.ContainsKey(usr.Id))
                            result.Add(usr.Id, 0);
                        result[usr.Id] = result[usr.Id] + item.Total * item2.Percent;
                        alreadyDone = true; 
                    }
                }
                if (!alreadyDone)
                {
                    foreach (User usr in users)
                    {
                        if (usr.Id != -1)
                        {
                            if (!result.ContainsKey(usr.Id))
                                result.Add(usr.Id, 0);
                            result[usr.Id] = result[usr.Id] + item.Total * proportion;
                        }
                    }
                }
            }
            syntheses.Clear();
            foreach (User usr in users) 
            {
                if (usr.Id != -1)
                {
                    if (!result.ContainsKey(usr.Id)) 
                    {
                        result.Add(usr.Id, 0);
                    }
                    result[usr.Id] = result[usr.Id] + solde / (this.users.Count - 1);
                    syntheses.Add(new SynthesePerUser(usr.Id, result.ContainsKey(usr.Id) ? result[usr.Id] : 0.0));
                }

            }
        }

        private List<ComptaLine> getAllLinesForAccount(int idAccount)
        {
            return DAO.Compta.ComptaLinesDAO.getAllLinesForAccount(idAccount);
        }

        private List<CategoriesPerUser> getAllCategoriesPerUser(int idAccount)
        {
           return DAO.Compta.ComptaCategoriesDAO.getCategoriesPerUser(idAccount);
        }


        private void selectAccountCb_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ComboBox cb = (ComboBox)sender;
            Account acct = (Account)cb.SelectedValue;
            
            //idAccount = acct.Id;
            //soldAccount = acct.Sold;
            //this.allLines.ReplaceRange(ComptaLinesDAO.getComptaLines(idAccount));
            this.users.ReplaceRange(DAO.Compta.ComptaUsersDAO.getOwners(acct.Id));
            getSyntheseForAccount(acct.Id, acct.Sold);
            //if (AllLinesRb.IsChecked == true)
            //    addLinesSup();
        }

        private void gridControl1_Loaded(object sender, RoutedEventArgs e)
        {
            this.gridControl1.Columns["IdUser"].EditSettings = new ComboBoxEditSettings() { DisplayMember = "Login", ValueMember = "Id", ItemsSource = (this.Users) };

        }

        public class SynthesePerUser
        {
            private int idUser;
            private double amount;

            public int IdUser 
            {
                get
                {
                    return idUser;
                }
            }

            public double Amount
            {
                get
                {
                    return amount;
                }
            }

            public SynthesePerUser(int idUser, double amount)
            {
                this.idUser = idUser;
                this.amount = amount;
            }
            
        }
    }

    public class IsNegative : System.Windows.Markup.MarkupExtension,IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            return ((double) value)<0;
        }

        public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
        {
            throw new InvalidOperationException("IsNegative can only be used OneWay.");
        }

        public override object ProvideValue(IServiceProvider serviceProvider)
        {
            return this;
        }
    }

}
